#include <unistd.h>
#include <cerrno>
#include <cstring>
#include "work/exposeFunc.h"
#include "work/workglobal.h"
#include "work/luaManager.h"
#include "log.h"
#include "pkg.h"
#include <unordered_map>

/**
 * RPC发送给另一个业务进程函数
 * @param 序列化后的二进制字符串
 */
int _c_logic_send(lua_State* L){
    size_t len = 0;
    const char* str = luaL_checklstring(L, 1, &len);

    // 直接转发到另一个进程
    errno = 0;
    int ret = g_zmq0.SendMsg(str, len);// 注意不能使用strlen（二进制数据会被截断）
    if(ret == -1){
        const char * errStr = strerror(errno);
        lua_pushboolean(L, false);
        lua_pushstring(L, errStr);
        return 2;// false + 错误信息 共2个返回值
    }
    lua_pushboolean(L, true);
    return 1;
}

/**
 * RPC发送给网络进程函数
 * @param 序列化后的二进制字符串
 */
int _c_net_send(lua_State* L){
    size_t len = 0;
    const char* str = luaL_checklstring(L, 1, &len);

    // 直接转发到另一个进程
    errno = 0;
    int ret = g_zmq3.SendMsg(str, len);// 注意不能使用strlen（二进制数据会被截断）
    if(ret == -1){
        const char * errStr = strerror(errno);
        lua_pushboolean(L, false);
        lua_pushstring(L, errStr);
        return 2;// false + 错误信息 共2个返回值
    }
    lua_pushboolean(L, true);
    return 1;
}

/**
 * RPC发送给数据库进程函数
 * @param 序列化后的二进制字符串
 */
int _c_db_send(lua_State* L){
    size_t len = 0;
    const char* str = luaL_checklstring(L, 1, &len);

    // 直接转发到另一个进程
    errno = 0;
    int ret = g_zmq2.SendMsg(str, len);// 注意不能使用strlen（二进制数据会被截断）
    if(ret == -1){
        const char * errStr = strerror(errno);
        lua_pushboolean(L, false);
        lua_pushstring(L, errStr);
        return 2;// false + 错误信息 共2个返回值
    }
    lua_pushboolean(L, true);
    return 1;
}

/**
 * RPC发送给数据库进程函数
 * @param 序列化后的二进制字符串
 */
int _c_log_send(lua_State* L){
    size_t len = 0;
    const char* str = luaL_checklstring(L, 1, &len);

    // 直接转发到另一个进程
    errno = 0;
    int ret = g_zmq1.SendMsg(str, len);// 注意不能使用strlen（二进制数据会被截断）
    if(ret == -1){
        const char * errStr = strerror(errno);
        lua_pushboolean(L, false);
        lua_pushstring(L, errStr);
        return 2;// false + 错误信息 共2个返回值
    }
    lua_pushboolean(L, true);
    return 1;
}

/**
 * 由Lua层调用获取进程标识
 */
int _c_proc_type(lua_State* L){
    const char* type = (g_procType == 0) ? "master" : "game";
    lua_pushstring(L, type);
    return 1;
}






//------------------------------------------转发处理函数实现begin------------------------------------------
/**
 * 跟消息结构体处理函数实现也放在这里（单线程处理）
 * @param msg 消息结构体(是通过移动语义转移过来的)
 */
void HandleFunc(WorkMsg&& msg){
    // 根据结构体中记录的进程不同，进行不同处理
    if(msg.sendProc == "master" || msg.sendProc == "game"){
        DealRpcFromLogic(msg.data);
    }
    else if(msg.sendProc == "net"){
        DealRpcFromNet(msg.data);
    }
    // 等待后续补充....
}

/**
 * 业务模块转发给业务模块的逻辑函数
 */
void DealRpcFromLogic(const std::string& data){
    // 额外处理...
    g_luaMgr.DoLuaFunc(LOGIC_RECV, data.c_str(), data.size());
}

void DealRpcFromNet(const std::string& data){
    // 额外处理...
    g_luaMgr.DoLuaFunc(NET_RECV, data.c_str(), data.size());
}

//------------------------------------------转发处理函数实现end------------------------------------------




